package com.wxm.controller;

import com.alibaba.fastjson.JSONObject;
import com.wxm.config.TlPayProperties;
import com.wxm.eum.PaySceneEnum;
import com.wxm.eum.SignTypeEnum;
import com.wxm.param.TlCancelParam;
import com.wxm.param.TlQueryParam;
import com.wxm.param.TlRefundParam;
import com.wxm.param.TlUnifiedPayParam;
import com.wxm.result.TlCancelResult;
import com.wxm.result.TlQueryResult;
import com.wxm.result.TlRefundResult;
import com.wxm.result.TlUnifiedPayResult;
import com.wxm.service.TongLianService;
import com.wxm.utils.R;
import com.wxm.utils.TlUtils;
import com.wxm.vo.TlUnifiedPayInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.TreeMap;

/**
 * <p>
 *      通联支付Controller
 * </p>
 *
 * @author: wxm
 * @Date: 2023/4/7
 */
@Slf4j
@RestController
@RequestMapping("/tl")
public class TongLianController {
    @Autowired
    private TlPayProperties tlPayProperties;
    @Autowired
    private TongLianService tongLianService;

    /**
     * 获取统一支付信息
     * @param orderNo 订单号
     * @param payType 支付方式 {#{@link PaySceneEnum}} 该类型会直接影响payInfo的返回格式
     * @return R<TlPayInfoVo>
     */
    @GetMapping("/pay-info")
    public R<TlUnifiedPayInfoVo> unifiedPay(@RequestParam("orderNo") String orderNo, @RequestParam("payType") Integer payType){
        //微信openId
        String openId = "ooErp5EYqNeuPyuF66-LBluX44dU";
        //支付金额
        BigDecimal price = new BigDecimal("0.01");

        TlUnifiedPayParam param = new TlUnifiedPayParam();
        //支付金额x100 转为分
        param.setTrxAmt(price.multiply(new BigDecimal("100")).longValue());
        //支付单号
        param.setReqSn(orderNo);
        //随机字符串
        param.setRandomStr(TlUtils.getRandomStr());
        //支付成功回调URL 需要拼接好支付单号
        param.setNotifyUrl(tlPayProperties.getNotify() + "/" + orderNo);
        //终端IP
        param.setCusIp("127.0.0.1");
        //商户号
        param.setCusId(tlPayProperties.getCusid());
        //AppId
        param.setAppid(tlPayProperties.getAppid());
        //微信子id，只对微信支付有效
        param.setSubAppid(tlPayProperties.getSubAppid());
        //接口版本号
        param.setVersion(tlPayProperties.getVersion());
        //签名方式
        param.setSignType(SignTypeEnum.RSA.getCode());
        //30分超时
        param.setValidTime(30);
        //支付平台用户标识
        param.setAcct(openId);
        param.setBody(orderNo);
        String payInfo = tongLianService.unifiedPay(param, PaySceneEnum.getByCode(payType));

        //构建Vo
        return R.ok(new TlUnifiedPayInfoVo(orderNo,price,payType,payInfo));
    }

    /**
     * 支付回调
     * @param request request
     * @param response response
     * @param orderNo 订单号
     */
    @PostMapping("/pay/notify/{orderNo}")
    public void payNotify(HttpServletRequest request, HttpServletResponse response,@PathVariable String orderNo) throws IOException {
        //通知传输的编码为GBK，强制转UTF-8
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        JSONObject param = TlUtils.getTlNotifyParam(request);
        log.info("通联回调 -> 参数：{}",param.toJSONString());
        try{
            //校验签名
            boolean b = TlUtils.validSign(param, tlPayProperties.getTlRsaPublicKey(), TlUtils.getSignType(tlPayProperties.getSignType()));
            if (b){
                TlUnifiedPayResult result = param.toJavaObject(TlUnifiedPayResult.class);
                log.info("通联支付回调成功 订单号:{} 流水号:{}",orderNo,result.getTrxid());
            }else {
                log.info("通联支付回调验签失败：{}", orderNo);
            }
        }catch (Exception e){
            log.error("通联支付回调处理失败 - {}", orderNo,e);
            R.exception("通联支付回调处理失败 - " + orderNo);
        }

        //返回success
        response.getOutputStream().write("success".getBytes());
        response.flushBuffer();
    }


    /**
     * 交易撤销（只能撤销当日交易并全额退款）
     * @param orderNo 订单号
     * @param transactionId 支付流水号
     * @return R<TlCancelResult>
     */
    @PostMapping("/cancel")
    public R<TlCancelResult> cancel(@RequestParam("orderNo")String orderNo,@RequestParam("transactionId") String transactionId){
        //交易金额
        BigDecimal refundTotal = new BigDecimal("0.01");

        TlCancelParam param = new TlCancelParam();
        //商户号
        param.setCusId(tlPayProperties.getCusid());
        //AppId
        param.setAppid(tlPayProperties.getAppid());
        //交易订单号
        param.setReqSn(orderNo);
        //交易金额[单位为分]
        param.setTrxAmt(refundTotal.multiply(new BigDecimal("100")).longValue());
        //支付流水号
        param.setOldTrxId(transactionId);
        //随机字符串
        param.setRandomStr(TlUtils.getRandomStr());
        //签名类型
        param.setSignType(SignTypeEnum.RSA.getCode());
        return R.ok(tongLianService.cancel(param));
    }

    /**
     * 交易退款（支持部分金额退款，隔天交易退款）
     * @param orderNo 订单号
     * @return R<TlRefundResult>
     */
    @PostMapping("/refund")
    public R<TlRefundResult> refund(@RequestParam("orderNo")String orderNo){
        //退款金额
        BigDecimal refundTotal = new BigDecimal("0.01");

        TlRefundParam param = new TlRefundParam();
        //商户号
        param.setCusId(tlPayProperties.getCusid());
        //AppId
        param.setAppid(tlPayProperties.getAppid());
        //交易订单号
        param.setReqSn(orderNo);
        //支付单号
        param.setOldReqSn(orderNo);
        //退款金额[单位为分]
        param.setTrxAmt(refundTotal.multiply(new BigDecimal("100")).longValue());
        //随机字符串
        param.setRandomStr(TlUtils.getRandomStr());
        //签名类型
        param.setSignType(SignTypeEnum.RSA.getCode());
        return R.ok(tongLianService.refund(param));
    }

    /**
     * 交易查询
     * @param orderNo 订单号
     * @return R<TlQueryResult>
     */
    @PostMapping("/query")
    public R<TlQueryResult> query(@RequestParam("orderNo")String orderNo){
        TlQueryParam param = new TlQueryParam();
        //商户号
        param.setCusId(tlPayProperties.getCusid());
        //AppId
        param.setAppid(tlPayProperties.getAppid());
        //交易订单号
        param.setReqSn(orderNo);
        //随机字符串
        param.setRandomStr(TlUtils.getRandomStr());
        //签名类型
        param.setSignType(SignTypeEnum.RSA.getCode());
        return R.ok(tongLianService.query(param));
    }
}
